package JIndicators;

import com.dukascopy.api.IConsole;
import com.dukascopy.api.IIndicators;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.indicators.*;

public class FXCorrelator_v01  implements IIndicator {
	
	private IndicatorInfo indicatorInfo;    
    private InputParameterInfo[] inputParameterInfos;
    private OptInputParameterInfo[] optInputParameterInfos;
    private OutputParameterInfo[] outputParameterInfos;
    //Indicator input used in calculations
    private double[][] inputs = new double[7][];
    //Default value of optional parameter
    private int timePeriod = 200;
    private int _Delta = 3;
    //Array of indicator output values
    private double[][] outputs = new double[8][];
	
    private IIndicator iMA_EURUSD;
    private IIndicator iMA_GBPUSD;
    private IIndicator iMA_AUDUSD;
    private IIndicator iMA_USDCHF;
    private IIndicator iMA_USDJPY;
    private IIndicator iMA_NZDUSD;
    private IIndicator iMA_USDCAD;
    
    private IConsole console;
    
	@Override
	public void onStart(IIndicatorContext context) {
		// TODO Auto-generated method stub
		
		IIndicatorsProvider indicatorsProvider = context.getIndicatorsProvider();
		iMA_EURUSD = indicatorsProvider.getIndicator("LWMA");
		iMA_GBPUSD = indicatorsProvider.getIndicator("LWMA");
		iMA_AUDUSD = indicatorsProvider.getIndicator("LWMA");
		iMA_USDCHF = indicatorsProvider.getIndicator("LWMA");
		iMA_USDJPY = indicatorsProvider.getIndicator("LWMA");
		iMA_NZDUSD = indicatorsProvider.getIndicator("LWMA");
		iMA_USDCAD = indicatorsProvider.getIndicator("LWMA");
		
		console = context.getConsole();
		
		indicatorInfo = new IndicatorInfo("FXCorrelator", "Power of different currences", "My indicators", false, false, false, 7, 1, 8);
		
		InputParameterInfo eurusd = new InputParameterInfo("EURUSD", InputParameterInfo.Type.DOUBLE);
		eurusd.setInstrument(Instrument.EURUSD);
		eurusd.setAppliedPrice(IIndicators.AppliedPrice.CLOSE);
		eurusd.setOfferSide(OfferSide.BID);
		
		InputParameterInfo gbpusd = new InputParameterInfo("GBPUSD", InputParameterInfo.Type.DOUBLE);
		gbpusd.setInstrument(Instrument.GBPUSD);
		gbpusd.setAppliedPrice(IIndicators.AppliedPrice.CLOSE);
		gbpusd.setOfferSide(OfferSide.BID);
		
		InputParameterInfo audusd = new InputParameterInfo("AUDUSD", InputParameterInfo.Type.DOUBLE);
		audusd.setInstrument(Instrument.AUDUSD);
		audusd.setAppliedPrice(IIndicators.AppliedPrice.CLOSE);
		audusd.setOfferSide(OfferSide.BID);
		
		InputParameterInfo usdchf = new InputParameterInfo("USDCHF", InputParameterInfo.Type.DOUBLE);
		usdchf.setInstrument(Instrument.USDCHF);
		usdchf.setAppliedPrice(IIndicators.AppliedPrice.CLOSE);
		usdchf.setOfferSide(OfferSide.BID);
		
		InputParameterInfo usdjpy = new InputParameterInfo("USDJPY", InputParameterInfo.Type.DOUBLE);
		usdjpy.setInstrument(Instrument.USDJPY);
		usdjpy.setAppliedPrice(IIndicators.AppliedPrice.CLOSE);
		usdjpy.setOfferSide(OfferSide.BID);
		
		InputParameterInfo nzdusd = new InputParameterInfo("NZDUSD", InputParameterInfo.Type.DOUBLE);
		nzdusd.setInstrument(Instrument.NZDUSD);
		nzdusd.setAppliedPrice(IIndicators.AppliedPrice.CLOSE);
		nzdusd.setOfferSide(OfferSide.BID);
		
		InputParameterInfo usdcad = new InputParameterInfo("USDCAD", InputParameterInfo.Type.DOUBLE);
		usdcad.setInstrument(Instrument.USDCAD);
		usdcad.setAppliedPrice(IIndicators.AppliedPrice.CLOSE);
		usdcad.setOfferSide(OfferSide.BID);
		
		inputParameterInfos = new InputParameterInfo[] {eurusd,
														gbpusd,
														audusd,
														usdchf,
														usdjpy,
														nzdusd,
														usdcad};
		
		optInputParameterInfos = new OptInputParameterInfo[] {
				new OptInputParameterInfo("Time period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(200, 2, 300, 1))};
		
		outputParameterInfos = new OutputParameterInfo[] 
		                                               {new OutputParameterInfo("EUR", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.LINE), 
		                            	        		new OutputParameterInfo("USD", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.LINE),
		                            	        		new OutputParameterInfo("GBP", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.LINE),
		                            	        		new OutputParameterInfo("AUD", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.LINE),
		                            	        		new OutputParameterInfo("CHF", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.LINE),
		                            	        		new OutputParameterInfo("JPY", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.LINE),
		                            	        		new OutputParameterInfo("NZD", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.LINE),
		                            	        		new OutputParameterInfo("CAD", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.LINE)};
	}
	
	@Override
	public IndicatorInfo getIndicatorInfo() {
		return indicatorInfo;
	}

	@Override
	public InputParameterInfo getInputParameterInfo(int index) {
		if (index <= inputParameterInfos.length) {
            return inputParameterInfos[index];
        }
        return null;
	}

	@Override
	public OptInputParameterInfo getOptInputParameterInfo(int index) {
		if (index <= optInputParameterInfos.length) {
	           return optInputParameterInfos[index];
	       }
	    return null;
	}

	@Override
	public OutputParameterInfo getOutputParameterInfo(int index) {
		if (index <= outputParameterInfos.length) {
            return outputParameterInfos[index];
        }
		return null;
	}

	@Override
	public void setInputParameter(int index, Object array) {
		inputs[index] = (double[]) array;
	}

	@Override
	public void setOptInputParameter(int index, Object value) {
		timePeriod = (Integer) value;
	}

	@Override
	public void setOutputParameter(int index, Object array) {
		outputs[index] = (double[]) array;
	}

	@Override
	public int getLookback() {
		//return iMA_EURUSD.getLookback();
		return timePeriod + _Delta;
	}

	@Override
	public int getLookforward() {
		return 0;
	}

	@Override
	public IndicatorResult calculate(int startIndex, int endIndex) {
		
		if (startIndex > endIndex) {
	           return new IndicatorResult(0, 0);
	    }
		
		double [] emaOutput1 = new double[endIndex];
        iMA_EURUSD.setInputParameter(0, inputs[0]);
        iMA_EURUSD.setOptInputParameter(0, timePeriod);
        iMA_EURUSD.setOutputParameter(0, emaOutput1);
        iMA_EURUSD.calculate(startIndex, endIndex);
		
		double [] emaOutput2 = new double[endIndex];
        iMA_GBPUSD.setInputParameter(0, inputs[1]);
        iMA_GBPUSD.setOptInputParameter(0, timePeriod);
        iMA_GBPUSD.setOutputParameter(0, emaOutput2);
        iMA_GBPUSD.calculate(startIndex, endIndex);
        
        double [] emaOutput3 = new double[endIndex];
        iMA_AUDUSD.setInputParameter(0, inputs[2]);
        iMA_AUDUSD.setOptInputParameter(0, timePeriod);
        iMA_AUDUSD.setOutputParameter(0, emaOutput3);
        iMA_AUDUSD.calculate(startIndex, endIndex);
        
        double [] emaOutput4 = new double[endIndex];
        iMA_USDCHF.setInputParameter(0, inputs[3]);
        iMA_USDCHF.setOptInputParameter(0, timePeriod);
        iMA_USDCHF.setOutputParameter(0, emaOutput4);
        iMA_USDCHF.calculate(startIndex, endIndex);
        
        double [] emaOutput5 = new double[endIndex];
        iMA_USDJPY.setInputParameter(0, inputs[4]);
        iMA_USDJPY.setOptInputParameter(0, timePeriod);
        iMA_USDJPY.setOutputParameter(0, emaOutput5);
        iMA_USDJPY.calculate(startIndex, endIndex);
        
        double [] emaOutput6 = new double[endIndex];
        iMA_NZDUSD.setInputParameter(0, inputs[5]);
        iMA_NZDUSD.setOptInputParameter(0, timePeriod);
        iMA_NZDUSD.setOutputParameter(0, emaOutput6);
        iMA_NZDUSD.calculate(startIndex, endIndex);
        
        double [] emaOutput7 = new double[endIndex];
        iMA_USDCAD.setInputParameter(0, inputs[6]);
        iMA_USDCAD.setOptInputParameter(0, timePeriod);
        iMA_USDCAD.setOutputParameter(0, emaOutput7);
        iMA_USDCAD.calculate(startIndex, endIndex);
        
        int j = 0;
        double A1,A2,A3,A4,A5,A6,A7;
        double EUR,USD,GBP,AUD,CHF,JPY,NZD,CAD;
        
        for (j = startIndex; j <= (endIndex-_Delta); j++) {
        	
        	try{
	        	
        		A1 = emaOutput1[j] - emaOutput1[j+_Delta];
        		A2 = emaOutput2[j] - emaOutput2[j+_Delta];
        		A3 = emaOutput3[j] - emaOutput3[j+_Delta];
        		A4 = emaOutput4[j+_Delta] - emaOutput4[j];
        		A5 = (emaOutput5[j+_Delta] - emaOutput5[j])/100;
        		A6 = emaOutput6[j] - emaOutput6[j+_Delta];
        		A7 = emaOutput7[j+_Delta] - emaOutput7[j];
        		
        		EUR = A1-(A2+A3+A4+A5+A6+A7)/6;
        		USD = (A1+A2+A3+A4+A5+A6+A7)/7;
        		GBP = A2-(A1+A3+A4+A5+A6+A7)/6;
        		AUD = A3-(A1+A2+A4+A5+A6+A7)/6;  
        		CHF = A4-(A1+A2+A3+A5+A6+A7)/6; 
        		JPY = A5-(A1+A2+A3+A4+A6+A7)/6; 
        		NZD = A6-(A1+A2+A3+A4+A5+A7)/6;
        		CAD = A7-(A1+A2+A3+A4+A5+A6)/6;
        		
        		outputs[0][j] = EUR;
        		outputs[1][j] = USD;
        		outputs[2][j] = GBP;
        		outputs[3][j] = AUD;
        		outputs[4][j] = CHF;
        		outputs[5][j] = JPY;
        		outputs[6][j] = NZD;
        		outputs[7][j] = CAD;
        	}
        	catch (java.lang.ArrayIndexOutOfBoundsException ex) {
				break;
			}
        }
        
        return new IndicatorResult(startIndex, j);
	}
	 
}